package com.github.hiling.common.oauth;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

/**
 * Author by hiling, Date on 12/14/2018.
 */
public class JwtUtils {

    private static final Logger log = Logger.getLogger("JwtUtils");
    /**
     * 用户编号：sub = Subject, JWT面向的用户
     */
    public static final String USER_ID_KEY = "sub";


    /**
     * 客户端编号：aud = Audience 接受JWT的一方
     */
    public static final String CLIENT_ID_KEY = "aud";

    /**
     * 用户名称, 自定义属性
     */
    public static final String USER_NAME_KEY = "unm";


    /**
     * 授权范围，自定义属性
     */
    public static final String SCOPE_KEY = "scp";

    /**
     * 使用HS256签名算法和生成的signingKey最终的Token,claims中是有效载荷
     *
     * @param userName   = sub JWT面向的用户 (User)
     * @param clientId   = aud 接受JWT的一方 （Client）
     * @param expiration = exp  过期时间
     * @param issuedAt   = iat  签发时间
     * @return
     */
    public static String createJavaWebToken(Long userId, String userName, String clientId, String scope,
                                            Date expiration, Date issuedAt) {

        Map<String, Object> claimsMap = new HashMap<>(8);
        claimsMap.put(USER_ID_KEY, userId == null ? "0" : userId.toString());
        claimsMap.put(USER_NAME_KEY, userName);
        claimsMap.put(CLIENT_ID_KEY, clientId);
        claimsMap.put(SCOPE_KEY, scope);

        return Jwts.builder()
                .claims(claimsMap)
                .expiration(expiration)
                .issuedAt(issuedAt)
                .signWith(getSecretKey())
                .compact();
    }

    /**
     * 解析Token，同时也能验证Token，当验证失败返回null
     */
    public static Map<String, Object> parserJavaWebToken(String jwt) {

        if (jwt == null || jwt.isEmpty()) {
            return null;
        }

        if (jwt.startsWith("Bearer ")) {
            jwt = jwt.substring(7);
        }

        try {
            return Jwts.parser().verifyWith(getSecretKey()).build().parseSignedClaims(jwt).getPayload();
        } catch (Exception e) {
            log.warning("json web token verify failed. error message:" + e.getMessage());
            return null;
        }
    }

    private static SecretKey getSecretKey() {
        return Keys.hmacShaKeyFor(Decoders.BASE64.decode("RYFcmDVJ7ltmACFkX9hdGC8i6G7TBtttfjwXpieiGhNeYfMe7056TmycteotI5xw"));
    }
}